package com.nicefact.mailmonitor.workflow.impl.task;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import com.google.appengine.api.blobstore.BlobInfo;
import com.google.appengine.api.blobstore.BlobInfoFactory;
import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.blobstore.BlobstoreService;
import com.google.appengine.api.blobstore.BlobstoreServiceFactory;
import com.nicefact.mailmonitor.entity.AppAdmin;
import com.nicefact.mailmonitor.entity.AppUser;
import com.nicefact.mailmonitor.entity.LogMessage;
import com.nicefact.mailmonitor.entity.OAuthEntity;
import com.nicefact.mailmonitor.service.AppAdminService;
import com.nicefact.mailmonitor.service.AppFileService;
import com.nicefact.mailmonitor.service.AppUserService;
import com.nicefact.mailmonitor.service.LogMessageService;
import com.nicefact.mailmonitor.service.OauthService;
import com.nicefact.mailmonitor.util.CSVFileReader;
import com.nicefact.mailmonitor.vo.AppProperties;
import com.nicefact.mailmonitor.workflow.AbstractWorkflowTask;
import com.nicefact.mailmonitor.workflow.WorkflowContext;
import com.nicefact.mailmonitor.workflow.WorkflowExecutionException;
import com.nicefact.mailmonitor.workflow.impl.context.ImportUserContext;

public class ImportUserTask extends AbstractWorkflowTask {
	@Autowired
	AppProperties appProperties;

	@Autowired private LogMessageService logMessageService;
	
	@Autowired
	AppUserService appUserService;
	
	@Autowired
	AppAdminService appAdminService;

	@Autowired
	AppFileService appFileService;
	
	@Autowired
	OauthService oauthService;


	@Override
	public WorkflowContext execute(WorkflowContext context)
			throws WorkflowExecutionException {
			ImportUserContext importUserContext = (ImportUserContext) context;
			String adminEmail = importUserContext.getAdminEmail();
			BlobKey blobKey = importUserContext.getBlobKey();
			LogMessage logMessage = new LogMessage();
			logMessage.setCreatedBy(adminEmail);
			if (blobKey != null) {
				BlobstoreService blobstoreService = BlobstoreServiceFactory
						.getBlobstoreService();
				try {
					Thread.sleep(5000);
				} catch (InterruptedException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				BlobInfo blobInfo = new BlobInfoFactory().loadBlobInfo(blobKey);
				//System.out.println("blobInfo : " + blobInfo);

				try {
					byte[] data = blobstoreService.fetchData(blobKey, 0,
							blobInfo.getSize());
					InputStream stream = new ByteArrayInputStream(data);
					CSVFileReader x = new CSVFileReader(stream);
					x.ReadFile();
					List<AppUser> appUsers = createUsersList(
							x.getStoreValuesList(), adminEmail);
					List<AppUser> existingUsers = appUserService.getAllUsers(adminEmail);
					appUsers.removeAll(existingUsers);
					updateExistingUserDetails(existingUsers, appUsers);
					saveNewUsers(appUsers, adminEmail);
					updateAppAdminUserCount(appUsers.size(),adminEmail);
					logMessage.setMessage("All contacts imported");
				} catch (Exception e) {
					// TODO Auto-generated catch block
					logMessage.setMessage("contacts import failed");
					System.out.println("contacts import failed due to : "
							+ e.getMessage());
					e.printStackTrace();
				}
				logMessageService.save(logMessage);
				System.out.println("contacts imported");
				try {
					blobstoreService.delete(blobKey);
				} catch (Exception e) {
					System.out.println("Failed to delete file from blobstore");
				}
			} else {
				System.out.println("blob key is null");
			}
		return context;
	}

	private void updateAppAdminUserCount(int size, String adminEmail) {
		AppAdmin appAdmin = appAdminService.get(adminEmail);
		Integer users = appAdmin.getNoOfAccounts() + size;
		appAdmin.setNoOfAccounts(users);
		appAdminService.save(appAdmin);
		
	}

	private void saveNewUsers(List<AppUser> appUsers, String adminEmail) {
		Set<String> emails = new HashSet<String>();
		for(AppUser appUser:appUsers){
			if (emails.add(appUser.getEmail())) {
				createAccount(adminEmail, appUser);
				appUserService.save(appUser);
			}
		}
		
	}

	private String createAccount(String adminEmail, AppUser appUser) {
		String reply = "Mail sent asking for authorization to "+ appUser.getEmail() ;
		OAuthEntity oAuthEntity = oauthService.getRequestToken(appUser.getEmail());
		if (oAuthEntity != null) {
			
			String approvalUrl = oAuthEntity.getAuthorizationUrl();
			String oauthToken = oAuthEntity.getKey();
			String oauthSecret = oAuthEntity.getSecret();
			appUser.setOauthtokensecret(oauthSecret);
			appUser.setOauthtoken(oauthToken);
			appUserService.sendApprovalMailToUser(appProperties.getUsername(),adminEmail,appUser.getEmail(), approvalUrl);
			System.out.println("approval Url : " + approvalUrl);
		} else {
			System.out.println("oauthParameters is null");
		}
		return reply;
	}
	
	private void updateExistingUserDetails(List<AppUser> existingUsers,
			List<AppUser> appUsers) {
		Map<String, AppUser> map = new HashMap<String, AppUser>();
		for(AppUser appUser : appUsers){
			map.put(appUser.getEmail(), appUser);
		}
		
		for(AppUser appUser : existingUsers){
			if(map.containsKey(appUser.getEmail())){
				AppUser updatedUser = map.get(appUser.getEmail());
				appUser.setFirstName(updatedUser.getFirstName());
				appUser.setLastName(updatedUser.getLastName());
				appUserService.save(appUser);
				appUsers.remove(updatedUser);
			}
		}
		
	}

	private List<AppUser> createUsersList(
			ArrayList<ArrayList<String>> storeValuesList, String adminEmail) {
		List<AppUser> appUsers = new ArrayList<AppUser>();
		for (int i = 1; i < storeValuesList.size(); i++) {
			ArrayList<String> row = storeValuesList.get(i);

			AppUser appUser = createAppUser(row,adminEmail);
			if (appUser != null) {
				appUsers.add(appUser);
			}
		}
		return appUsers;
	}

	private AppUser createAppUser(ArrayList<String> row, String adminEmail) {
		AppUser appUser = null;
		String email = row.get(0);
		String firstName ="";
		String lastName = "";
		if(row.size()>1){
firstName = StringUtils.isBlank(row.get(1)) ? "" : row.get(1);
lastName = StringUtils.isBlank(row.get(2)) ? "" : row.get(2);
		}
		if (!StringUtils.isBlank(email)) {
			appUser = new AppUser(email.trim(), firstName, lastName,adminEmail);
		}
		return appUser;
	}

}
